package com.thoughtworks.biblioteca;

import java.util.List;

// Understands a public library system that handles a catalog of books and
// movies

enum MainMenuChoice {
	LIST_BOOK_CATALOG, CHECKOUT_BOOK, CHECK_LIBRARY_NUMBER, LIST_MOVIE_CATALOG, RATE_MOVIES, ADD_MOVIE, EXIT

}

public class Biblioteca {
	public static final boolean CHECKOUT_SUCCESSFUL = true;
	public static final boolean CHECKOUT_FAILED = false;
	private boolean isUserLoggedIn = false;
	private boolean isLibrarianLoggedIn = false;
	MainMenuChoice mainMenuChoice;
	String loggedUser;
	private User user;
	BooksCatalog booksCatalog;
	MoviesCatalog moviesCatalog;
	MovieDB movieDB;
	BibliotecaConsole bibliotecaConsole;

	public Biblioteca(BibliotecaConsole bibliotecaConsole) {
		booksCatalog = new BooksCatalog();
		moviesCatalog = new MoviesCatalog();
		this.bibliotecaConsole = bibliotecaConsole;
		movieDB = new MovieDB();
	}

	public void startBiblioteca() {

		while (true) {
			bibliotecaConsole.displayMainMenu(isLibrarianLoggedIn);
			int menuChoice = 0;
			menuChoice = bibliotecaConsole.getInputFromUser();
			switch (menuChoice) {
			case 1:
				bibliotecaConsole.displayBooksCatalog(booksCatalog);
				break;
			case 2:
				checkoutBook();
				break;
			case 3:
				checkLibraryNumber();
				break;
			case 4:
				bibliotecaConsole.displayMovieCatalog(moviesCatalog,
						isUserLoggedIn, loggedUser);
				break;
			case 5:
				rateMovies();
				break;
			case 6:
				requestMovies();
				break;
			case 7:
				requestedMovies();
				break;
			case 8:
				addNewMovie();
				break;
			case 9:
				if (isLibrarianLoggedIn) {
					System.out.println("Enter the request id to close it:");
					int requestID = bibliotecaConsole.getInputFromUser();
					movieDB.closeRequest(requestID);
					break;
				}

			case 10:
				if (isLibrarianLoggedIn)
					System.exit(0);
			default:
				System.out.println("\n");
				System.out.println("Please enter a valid menu choice");
			}
		}
	}

	private void requestedMovies() {
		if (isLoginFailed())
			return;
		MovieDB movieDB = new MovieDB();
		List<MovieRequest> movieRequestList = getListOfRequestsBasedOnTypeOfUser(movieDB);
		System.out.format("%-5s%-10s%-25s%-10s\n", "Id", "UserName", "Movie",
				"Status");
		for (MovieRequest request : movieRequestList) {
			request.display();
		}
	}

	private List<MovieRequest> getListOfRequestsBasedOnTypeOfUser(
			MovieDB movieDB) {
		List<MovieRequest> movieRequestList = movieDB.getRequests(loggedUser);
		if (isLibrarianLoggedIn)
			movieRequestList = movieDB.getAllRequests();
		return movieRequestList;
	}

	private void requestMovies() {
		if (isLoginFailed())
			return;
		String movieName = bibliotecaConsole.getNameOfTheMovie();
		Movie requestedMovie = movieDB.getMovie(movieName);
		if (requestedMovie == null) {
			System.out.println("Movie not found");
			return;
		}
		bibliotecaConsole.displayRequestedMovieDetails(movieName, movieDB,
				requestedMovie, loggedUser);
		requestsMenu(movieName);

	}

	private void requestsMenu(String movieName) {
		bibliotecaConsole.displayRequestsMenu();
		int requestMenuChoice = 0;
		requestMenuChoice = bibliotecaConsole.getInputFromUser();
		if (requestMenuChoice == 1) {

			System.out.println("Your request has been saved.");
			movieDB.addRequest(movieName, loggedUser);
			moviesCatalog = moviesCatalog.refreshMoviesCatalog();
		}
	}

	void addNewMovie() {
		if (!isLibrarianLoggedIn)
			System.exit(0);
		addNewMovieByLibrarian();
	}

	void addNewMovieByLibrarian() {
		String newMovieName = bibliotecaConsole.getNameOfTheMovie();
		String newMovieDirector = bibliotecaConsole.getMovieDirector();
		String newMovieRating = "" + bibliotecaConsole.getRatingForMovie();
		Movie newMovie = new Movie(newMovieName, newMovieDirector,
				newMovieRating);
		newMovie.add();
		moviesCatalog = moviesCatalog.refreshMoviesCatalog();
	}

	private void rateMovies() {
		if (isLoginFailed())
			return;
		String movieName = bibliotecaConsole.getNameOfTheMovie();
		Movie requestedMovie = movieDB.getMovie(movieName);
		if (requestedMovie == null) {
			System.out.println("Movie not found");
			return;
		}
		bibliotecaConsole.displayRequestedMovieDetails(movieName, movieDB,
				requestedMovie, loggedUser);
		ratingsMenu(movieName);
	}

	private boolean isLoginFailed() {
		return !isUserLoggedIn && !promtUserLogin();
	}

	private void ratingsMenu(String movieName) {
		bibliotecaConsole.displayRatingsMenu();
		int ratingMenuChoice = 0;
		ratingMenuChoice = bibliotecaConsole.getInputFromUser();
		if (ratingMenuChoice == 1) {
			int userRating = bibliotecaConsole.getRatingForMovie();
			if (isUserRatingInValid(userRating)) {
				bibliotecaConsole.displayWrongRatingMessage();
				return;
			}
			movieDB.updateRating(loggedUser, movieName, userRating);
			moviesCatalog = moviesCatalog.refreshMoviesCatalog();
		}
	}

	boolean isUserRatingInValid(int userRating) {
		return userRating <= 0 || userRating > 10;
	}

	private void checkLibraryNumber() {

		if (isUserLoggedIn) {
			System.out.println("Your library number is: " + loggedUser);
			return;
		}
		handleNewSession();
	}

	private void handleNewSession() {
		String sessionUserName;
		sessionUserName = obtainUserNameForSession();
		bibliotecaConsole.displayUserNameMessage(sessionUserName);
		if (isSetPasswordForNewUser(user)) {
			isUserLoggedIn = true;
			System.out.println("You have been logged in.");
		}
		loggedUser = sessionUserName;
	}

	private String obtainUserNameForSession() {
		if (loggedUser == null) {
			return generateUserNameForNewSession();
		}
		return loggedUser;
	}

	private String generateUserNameForNewSession() {
		String generatedUserName;
		UserNameGenerator userNameGenerator = new UserNameGenerator();
		generatedUserName = userNameGenerator.generate();
		user = new User(generatedUserName);
		return generatedUserName;
	}

	void checkoutBook() {
		int bookNumber = bibliotecaConsole.getBookToCheckOut();
		boolean checkoutStatus = booksCatalog.checkoutBook(bookNumber);
		bibliotecaConsole.displayCheckoutMessage(checkoutStatus);
	}

	boolean isSetPasswordForNewUser(User newUser) {

		boolean isPasswordCorrect = false;
		bibliotecaConsole.displayNewUserPasswordRules();
		String password = null;
		while (!isPasswordCorrect) {
			password = bibliotecaConsole.readLoginPassword();
			isPasswordCorrect = checkPasswordForCorrectness(password);
			if (!isPasswordCorrect) {
				int passwordChoice = bibliotecaConsole.passwordSetMenu();
				if (passwordChoice == 0)
					return false;
			}
		}
		newUser.setPassword(password);
		System.out.println("Password has been set!");
		return true;
	}

	public boolean checkPasswordForCorrectness(String password) {
		return password.length() >= 6 && password.length() <= 10;
	}

	boolean promtUserLogin() {
		String userName = null;
		String password = null;
		while (!isUserLoggedIn) {
			userName = bibliotecaConsole.readLoginUserName();
			password = bibliotecaConsole.readLoginPassword();
			Login login = new Login();
			isUserLoggedIn = login.authenticateUser(userName, password);
			if (!isUserLoggedIn) {
				int loginChoice = bibliotecaConsole.wrongPasswordMenu();
				if (loginChoice == 0)
					return false;
			}
		}
		if (userName.equals("111-1111"))
			isLibrarianLoggedIn = true;
		loggedUser = new String(userName);
		return isUserLoggedIn;
	}

}
